#pragma once

#include"Log.hpp"
#include"ThreadPool.hpp"
#include<iostream>
#include<string>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<functional>


#include"InetAddr.hpp"

using namespace InetAddrMoudle;
using namespace LogMoudle;
using namespace ThreadPoolMoudle;


#define SOC(v) (sockaddr*)(v)


//const static std::string default_ip="127.0.0.1";
const static uint16_t default_port=8888;

const static int default_size=1024;

using func_t=std::function<void(const std::string &key,std::string *response)>;
using namespace LockModule;

class Udpserver{
public:
//缺省参数要放到后面
Udpserver(uint16_t port=default_port):_port(port)
{
    pthread_mutex_init(&_user_mutex,nullptr);
}

void Init()
{
    //创建socket
    _sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(_sockfd==-1)
    {
        LOG(Logevel::FATAL)<<"socket creat is error";
        exit(1);
    }

    LOG(Logevel::INFO)<<"socket creat success";

    //绑定套接字，指定网络信息

    struct sockaddr_in local;
    bzero(&local,sizeof(local));
    local.sin_family=AF_INET;
    local.sin_port=htons(_port);
    local.sin_addr.s_addr=INADDR_ANY;

    //接收来自任意服务器的请求

    int n=bind(_sockfd,SOC(&local),sizeof(local));

    if(n!=0)
    {
        LOG(Logevel::FATAL)<<"bind is error";
        exit(2);
    }

   
}

void AddOnlineUser(InetAddr addr)
{
    pthread_mutex_lock(&_user_mutex);
    for(auto &user :_online_user)
    {
        if(addr==user)
        {
            return;
        }
    }
    _online_user.push_back(addr);
    LOG(Logevel::INFO)<<addr.Ip()<<":"<<addr.Port()<<"is add to onlineuser list .....\n";
    pthread_mutex_unlock(&_user_mutex);
}

void Route(int sock ,const std::string &message)
{
    pthread_mutex_lock(&_user_mutex);
    for(auto &user:_online_user)
    {
        sendto(_sockfd,message.c_str(),message.size(),0,(struct sockaddr*)&user.GetAddr(),sizeof(user.GetAddr()));
        LOG(Logevel::INFO)<<"server send message to "<<user.Ip()<<":"<<user.Port()<<" message "<<message<<"\n";

    }
}

void Start()
{
    //存储发过来的信息
    char buffer[default_size];
    //服务器永不退出
    while(true)
    {
        struct sockaddr_in peer;
        socklen_t len=sizeof(peer);
        bzero(&peer,sizeof(peer));
        ssize_t n=recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,SOC(&peer),&len);

        if(n>0)
        {
            InetAddr addr(peer);
            AddOnlineUser(addr);
            buffer[n]=0;
            std::string message="[";
            message+=addr.Ip();
            message+=":";
            message+=std::to_string(addr.Port());
            message+="]# ";
            message+=buffer;
            func_t task=std::bind(&Udpserver::Route,this,_sockfd,message);
            ThreadPool<func_t>::GetInstance()->Enqueue(task);
        }
    }
}

~Udpserver()
{
    pthread_mutex_destroy(&_user_mutex);
}

private:
        std::string _ip;
        uint16_t _port;
        int _sockfd;

        std::vector<InetAddr> _online_user;//会被多个线程同时进行访问
        pthread_mutex_t _user_mutex;
        
        
};